home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #4 / Amiga Plus CD - 2000 - No. 4.iso / Tools / Dev / SpeakFreely_Src / gsm / src / toast.c < prev    next >
C/C++ Source or Header  |  2000-05-27  |  18KB  |  771 lines

  1. /*
  2.  * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
  3.  * Universitaet Berlin.  See the accompanying file "COPYRIGHT" for
  4.  * details.  THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
  5.  */
  6.  
  7. /* $Header: /home/kbs/jutta/src/gsm/gsm-1.0/src/RCS/toast.c,v 1.3 1993/01/29 18:19:25 jutta Exp $ */
  8.  
  9. #include        "toast.h"
  10.  
  11. /*  toast -- lossy sound compression using the gsm library.
  12.  */
  13.  
  14. char   * progname;
  15.  
  16. int    f_decode   = 0;     /* decode rather than encode     (-d) */
  17. int    f_cat       = 0;     /* write to stdout, not foo.gsm  (-c) */
  18. int    f_force    = 0;     /* force deletion         (-f) */
  19. int    f_precious = 0;     /* avoid deletion         (-p) */
  20. int    f_fast       = 0;     /* use faster fpt algorithm     (-F) */
  21. int    f_verbose  = 0;     /* debugging             (-V) */
  22.  
  23. struct stat instat;        /* stat (inname)         */
  24.  
  25. FILE    *in,     *out;
  26. char    *inname, *outname;
  27.  
  28. /*
  29.  *  The function (*output)() writes a frame of 160 samples given as
  30.  *  160 signed 16 bit values (gsm_signals) to <out>.
  31.  *  The function (*input)() reads one such frame from <in>.
  32.  *  The function (*init_output)() begins output (e.g. writes a header).,
  33.  *  The function (*init_input)() begins input (e.g. skips a header).
  34.  *
  35.  *  There are different versions of input, output, init_input and init_output
  36.  *  for different formats understood by toast; which ones are used 
  37.  *  depends on the command line arguments and, in their absence, the
  38.  *  filename; the fallback is #defined in toast.h
  39.  *
  40.  *  The specific implementations of input, output, init_input and init_output
  41.  *  for a format `foo' live in toast_foo.c.
  42.  */
  43.  
  44. int    (*output   ) P((gsm_signal *)),
  45.     (*input    ) P((gsm_signal *));
  46. int    (*init_input)  P(()),
  47.     (*init_output) P(());
  48.  
  49. static int    generic_init P0() { return 0; } /* NOP */
  50.  
  51. extern int    audio_init_input(), audio_init_output();
  52. extern int    ulaw_input   P((gsm_signal*)), ulaw_output   P((gsm_signal *));
  53. extern int    alaw_input   P((gsm_signal*)), alaw_output   P((gsm_signal *));
  54. extern int    linear_input P((gsm_signal*)), linear_output P((gsm_signal *));
  55.  
  56. struct fmtdesc {
  57.  
  58.     char * name, * longname, * suffix;
  59.  
  60.     int  (* init_input )  P(()),
  61.          (* init_output)  P(());
  62.  
  63.     int  (* input ) P((gsm_signal * )),
  64.          (* output) P((gsm_signal * ));
  65.  
  66. } f_audio = {
  67.                 "audio",
  68.                 "8 kHz, 8 bit u-law encoding with Sun audio header", ".au",
  69.         audio_init_input,
  70.         audio_init_output,
  71.         ulaw_input,
  72.         ulaw_output
  73. }, f_ulaw = {
  74.                 "u-law", "plain 8 kHz, 8 bit u-law encoding", ".u",
  75.         generic_init,
  76.         generic_init,
  77.         ulaw_input,
  78.         ulaw_output 
  79.  
  80. }, f_alaw = {
  81.                 "A-law", "8 kHz, 8 bit A-law encoding", ".A",
  82.         generic_init,
  83.         generic_init,
  84.         alaw_input,
  85.         alaw_output
  86.  
  87. }, f_linear = {
  88.                 "linear",
  89.                 "16 bit (13 significant) signed 8 kHz signal", ".l",
  90.         generic_init,
  91.         generic_init,
  92.         linear_input,
  93.         linear_output
  94. };
  95.  
  96. struct fmtdesc * alldescs[] = {
  97.     &f_audio,
  98.     &f_alaw,
  99.     &f_ulaw,
  100.     &f_linear,
  101.     (struct fmtdesc *)NULL
  102. };
  103.  
  104. #define DEFAULT_FORMAT    f_ulaw        /* default audio format, others */
  105.                     /* are: f_alaw,f_audio,f_linear */
  106. struct fmtdesc * f_format  = 0;
  107.  
  108. /*
  109.  *  basename + suffix of a pathname
  110.  */
  111. char * endname P1((name), char * name)
  112. {
  113.     if (name) {
  114.                 char * s = strrchr(name, '/');
  115.         if (s && s[1]) name = s + 1;
  116.     }
  117.     return name;
  118.  
  119. }
  120.  
  121. /*
  122.  *  Try to figure out what we're supposed to do from the argv[0], if
  123.  *  any, and set the parameters accordingly.
  124.  */
  125. static void parse_argv0 P1((av0), char * av0 )
  126. {
  127.     char    * c;
  128.     int    l;
  129.  
  130.         progname = av0 = endname(av0 ? av0 : "toast");
  131.  
  132.         /*  If the name starts with `un', we want to decode, not code.
  133.          *  If the name ends in `cat', we want to write to stdout,
  134.      *  and decode as well.
  135.      */
  136.  
  137.         if (!strncmp(av0, "un", 2)) f_decode = 1;
  138.         if (  (l = strlen(av0)) >= 3 /* strlen("cat") */
  139.            && !strcmp( av0 + l - 3, "cat" )) f_cat = f_decode = 1;
  140. }
  141.  
  142.  
  143. /*
  144.  *  Check whether the name (possibly generated by appending
  145.  *  .gsm to something else) is short enough for this system.
  146.  */
  147. int length_okay P1((name), char * name)
  148. {
  149.     long    max_filename_length = 0;
  150.     char    * end, * s, tmp;
  151.  
  152.         /* If our _pathname_ is too long, we'll usually not be
  153.          * able to open the file at all -- don't worry about that.
  154.      * 
  155.      * But if the _filename_ is too long, there is danger of
  156.      * silent truncation on some systems, which results
  157.      * in the target replacing the source!
  158.      */
  159.  
  160.     if (!name) return 0;
  161.     end = endname(name);
  162.  
  163. #ifdef    NAME_MAX
  164.     max_filename_length  = NAME_MAX;
  165. #else
  166. #ifdef    _PC_NAME_MAX
  167.  
  168.     /*  s = dirname(name)
  169.      */
  170.     if ((s = end) > name) {
  171.         if (s > name + 1) s--;
  172.         tmp = *s;
  173.         *s  = 0;
  174.     }
  175.  
  176.     errno = 0;
  177.         max_filename_length = pathconf(s > name ? name : ".", _PC_NAME_MAX);
  178.     if (max_filename_length == -1 && errno) {
  179.                 perror( s > name ? name : "." );
  180.         fprintf(stderr,
  181.                 "%s: cannot get dynamic filename length limit for %s.\n",
  182.                         progname, s > name ? name : ".");
  183.         return 0;
  184.     }
  185.     if (s > name) *s = tmp;
  186.  
  187. #endif /* _PC_NAME_MAX    */
  188. #endif /* !NAME_MAX    */
  189.  
  190.     if (max_filename_length > 0 && strlen(end) > max_filename_length) {
  191.         fprintf(stderr,
  192.                         "%s: filename \"%s\" is too long (maximum is %ld)\n",
  193.             progname, endname(name), max_filename_length );
  194.         return 0;
  195.     }
  196.  
  197.     return 1;
  198. }
  199.  
  200. /*
  201.  *  Return a pointer the suffix of a string, if any.
  202.  *  A suffix alone has no suffix, an empty suffix can not be had.
  203.  */
  204. static char * suffix P2((name, suf), char *name, char * suf) 
  205. {
  206.     int nlen = strlen(name);
  207.     int slen = strlen(suf);
  208.  
  209.     if (!slen || nlen <= slen) return (char *)0;
  210.     name += nlen - slen;
  211.     return memcmp(name, suf, slen) ? (char *)0 : name;
  212. }
  213.  
  214.  
  215. void catch_signals P1((fun), SIGHANDLER_T (*fun)()) 
  216. {
  217. #ifdef    SIGHUP
  218.     signal( SIGHUP,   fun );
  219. #endif
  220. #ifdef    SIGINT
  221.     signal( SIGINT,   fun );
  222. #endif
  223. #ifdef    SIGPIPE
  224.     signal( SIGPIPE,  fun );
  225. #endif
  226. #ifdef    SIGTERM
  227.     signal( SIGTERM,  fun );
  228. #endif
  229. #ifdef    SIGXFSZ
  230.     signal( SIGXFSZ,  fun );
  231. #endif
  232. }
  233.  
  234. static SIGHANDLER_T onintr P0()
  235. {
  236.     char * tmp = outname;
  237.  
  238. #ifdef    HAS_SYSV_SIGNALS
  239.     catch_signals( SIG_IGN );
  240. #endif
  241.  
  242.     outname = (char *)0;
  243.     if (tmp) (void)unlink(tmp);
  244.  
  245.     exit(1);
  246. }
  247.  
  248. /*
  249.  *  Allocate some memory and complain if it fails.
  250.  */
  251. static char * emalloc P1((len), int len)
  252. {
  253.     char * s;
  254.     if (!(s = malloc(len))) {
  255.                 fprintf(stderr, "%s: failed to malloc %d bytes -- abort\n",
  256.             progname, len);
  257.         onintr();
  258.         exit(1);
  259.     }
  260.     return s;
  261. }
  262.  
  263. static char* normalname P3((name, want, cut), char *name, char *want,char *cut)
  264. {
  265.     int    maxlen;
  266.     char    * s, * p;
  267.  
  268.     p = (char *)0;
  269.     if (!name) return p;
  270.  
  271.     maxlen = strlen(name) + 1 + strlen(want) + strlen(cut);
  272.     p = strcpy(emalloc(maxlen), name);
  273.  
  274.     if (s = suffix(p, cut)) strcpy(s, want);
  275.     else if (*want && !suffix(p, want)) strcat(p, want);
  276.  
  277.     return p;
  278. }
  279.  
  280. /*
  281.  *  Generate a `plain' (non-encoded) name from a given name.
  282.  */
  283. char * plainname P1((name), char *name)
  284. {
  285.         return normalname(name, "", SUFFIX_TOASTED );
  286. }
  287.  
  288. /*
  289.  *  Generate a `code' name (foo.Z) from a given name.
  290.  */
  291. char * codename P1((name), char *name)
  292. {
  293.         return normalname( name, SUFFIX_TOASTED, "" );
  294. }
  295.  
  296. /*
  297.  *  If we're supposed to ask (fileno (stderr) is a tty, and f_force not
  298.  *  set), ask the user whether to overwrite a file or not.
  299.  */
  300. static int ok_to_replace P1(( name ), char * name)
  301. {
  302.     int reply, c;
  303.  
  304.     if (f_force) return 1;            /* YES, do replace   */
  305.         if (!isatty(fileno(stderr))) return 0;  /* NO, don't replace */
  306.  
  307.     fprintf(stderr,
  308.                 "%s already exists; do you wish to overwrite %s (y or n)? ",
  309.         name, name);
  310.     fflush(stderr);
  311.  
  312.         for (c = reply = getchar(); c != '\n' && c != EOF; c = getchar()) ;
  313.         if (reply == 'y') return 1;
  314.  
  315.         fprintf(stderr, "\tnot overwritten\n");
  316.     return 0;
  317. }
  318.  
  319. void update_mode P0()
  320. {
  321.         if (!instat.st_nlink) return;           /* couldn't stat in */
  322.  
  323. #ifdef HAS_FCHMOD
  324.     if (fchmod(fileno(out), instat.st_mode & 07777)) {
  325.         perror(outname);
  326.                 fprintf(stderr, "%s: could not change file mode of \"%s\"\n",
  327.             progname, outname);
  328.     }
  329. #else 
  330.     if (outname && chmod(outname, instat.st_mode & 07777)) {
  331.         perror(outname);
  332.                 fprintf(stderr, "%s: could not change file mode of \"%s\"\n",
  333.             progname, outname);
  334.     }
  335. #endif /* HAS_FCHMOD */
  336. }
  337.  
  338. void update_own P0()
  339. {
  340.         if (!instat.st_nlink) return; /* couldn't stat in */
  341. #ifdef HAS_FCHOWN
  342.     (void)fchown(fileno(out), instat.st_uid, instat.st_gid);
  343. #else 
  344.     (void)chown(outname, instat.st_uid, instat.st_gid);
  345. #endif /* HAS_FCHOWN */
  346. }
  347.  
  348. void update_times P0()
  349. {
  350.         if (!instat.st_nlink) return;   /* couldn't stat in */
  351.  
  352. #ifdef HAS_UTIMES
  353.     if (outname) {
  354.         struct timeval tv[2];
  355.  
  356.         tv[0].tv_sec  = instat.st_atime;
  357.         tv[1].tv_sec  = instat.st_mtime;
  358.         tv[0].tv_usec = tv[1].tv_usec = 0;
  359.         (void) utimes(outname, tv);
  360.     }
  361. #else
  362. #ifdef HAS_UTIME
  363.  
  364.     if (outname) {
  365.  
  366. #ifdef    HAS_UTIMBUF
  367.         struct utimbuf ut;
  368.  
  369.         ut.actime     = instat.st_atime;
  370.         ut.modtime    = instat.st_mtime;
  371.  
  372. #    ifdef    HAS_UTIMEUSEC
  373.         ut.acusec     = instat.st_ausec;
  374.         ut.modusec    = instat.st_musec;
  375. #    endif    /* HAS_UTIMEUSEC */
  376.  
  377.         (void) utime(outname, &ut);
  378.  
  379. #else /* UTIMBUF */
  380.  
  381.         time_t ut[2];
  382.  
  383.         ut[0] = instat.st_atime;
  384.         ut[1] = instat.st_mtime;
  385.  
  386.         (void) utime(outname, ut);
  387.  
  388. #endif    /* UTIMBUF */
  389.     }
  390. #endif /* HAS_UTIME */
  391. #endif /* HAS_UTIMES */
  392. }
  393.  
  394.  
  395. static int okay_as_input P3((name,f,st), char* name, FILE* f, struct stat * st)
  396. {
  397. # ifdef HAS_FSTAT
  398.     if (fstat(fileno(f), st) < 0)
  399. # else
  400.     if (stat(name, st) < 0)
  401. # endif
  402.     {
  403.         perror(name);
  404.                 fprintf(stderr, "%s: cannot stat \"%s\"\n", progname, name);
  405.         return 0;
  406.     }
  407.  
  408.     if (!S_ISREG(st->st_mode)) {
  409.         fprintf(stderr,
  410.                         "%s: \"%s\" is not a regular file -- unchanged.\n",
  411.             progname, name);
  412.         return 0;
  413.     }
  414.     if (st->st_nlink > 1 && !f_cat && !f_precious) {
  415.         fprintf(stderr, 
  416.                       "%s: \"%s\" has %s other link%s -- unchanged.\n",
  417.                         progname,name,st->st_nlink - 1,"s" + (st->st_nlink<=2));
  418.         return 0;
  419.     }
  420.  
  421.     if (!f_decode && !f_cat && name && suffix( name, SUFFIX_TOASTED )) {
  422.         fprintf(stderr,
  423.                         "%s: %s already has \"%s\" suffix -- unchanged.\n",
  424.             progname, name, SUFFIX_TOASTED );
  425.         return 0;
  426.     }
  427.     return 1;
  428. }
  429.  
  430. static void prepare_io P1(( desc), struct fmtdesc * desc)
  431. {
  432.     output        = desc->output;
  433.     input        = desc->input;
  434.  
  435.     init_input  = desc->init_input;
  436.     init_output = desc->init_output;
  437. }
  438.  
  439. static struct fmtdesc * grok_format P1((name), char * name)
  440. {
  441.     char * c;
  442.     struct fmtdesc ** f;
  443.  
  444.     if (name) {
  445.         c = plainname(name);
  446.  
  447.         for (f = alldescs; *f; f++)
  448.             if (  (*f)->suffix
  449.                && *(*f)->suffix
  450.                && suffix(c, (*f)->suffix)) {
  451.  
  452.                 free(c);
  453.                 return *f;
  454.             }
  455.  
  456.         free(c);
  457.     }
  458.     return (struct fmtdesc *)0;
  459. }
  460.  
  461. static int open_input P2((name, st), char * name, struct stat * st)
  462. {
  463.     struct fmtdesc * f = f_format;
  464.  
  465.         st->st_nlink = 0;       /* indicates `undefined' value */
  466.     if (!name) {
  467.         inname = (char *)NULL;
  468.         in     = stdin;
  469.     }
  470.     else {
  471.         if (!f_decode) inname = strcpy(emalloc(strlen(name)+1), name);
  472.         else inname = codename(name);
  473.  
  474.         if (!(in = fopen(inname, READ))) {
  475.             perror(inname); /* not guaranteed to be valid here */
  476.                         fprintf(stderr, "%s: cannot open \"%s\" for reading\n",
  477.                 progname, inname);
  478.             return 0;
  479.         }
  480.         if (!okay_as_input(inname, in, st)) return 0;
  481.         if (!f) f = grok_format(inname);
  482.     }
  483.     prepare_io( f ? f : & DEFAULT_FORMAT );
  484.     return 1;
  485. }
  486.  
  487. static int open_output P1((name), char *name)
  488. {
  489.     if (!name || f_cat) {
  490.         out    = stdout;
  491.         outname = (char *)NULL;
  492.     }
  493.     else {
  494.         int outfd = -1;
  495.         char * o;
  496.  
  497.         o = (*(f_decode ? plainname : codename))(name);
  498.         if (!length_okay(o)) return 0;
  499.         if ((outfd = open(o, O_WRITE_EXCL, 0666)) >= 0)
  500.             out = fdopen(outfd, WRITE);
  501.         else if (errno != EEXIST) out = (FILE *)NULL;
  502.         else if (ok_to_replace(o)) out = fopen(o, WRITE);
  503.         else return 0;
  504.  
  505.         if (!out) {
  506.             perror(o);
  507.             fprintf(stderr,
  508.                                 "%s: can't open \"%s\" for writing\n",
  509.                 progname, o);
  510.             if (outfd >= 0) (void)close(outfd);
  511.             return 0;
  512.         }
  513.  
  514.         outname = o;
  515.     }
  516.     return 1;
  517. }
  518.  
  519. int process_encode P0()
  520. {
  521.     gsm        r;
  522.     int        n = 0;
  523.     gsm_signal    s[ 160 ];
  524.     gsm_frame    d;
  525.  
  526.     int        cc;
  527.  
  528.     if (!(r = gsm_create())) return -1;
  529.     (void)gsm_option(r, GSM_OPT_FAST,    &f_fast);
  530.     (void)gsm_option(r, GSM_OPT_VERBOSE, &f_verbose);
  531.  
  532.     while ((cc = (*input)(s)) > 0) {
  533.         if (cc < sizeof(s) / sizeof(*s))
  534.             memset((char *)(s+cc), 0, sizeof(s)-(cc * sizeof(*s)));
  535.         gsm_encode(r, s, d);
  536.         if (fwrite((char *)d, sizeof(d), 1, out) != 1) {
  537.                         perror(outname ? outname : "stdout");
  538.                         fprintf(stderr, "%s: error writing to %s\n",
  539.                                 progname, outname ? outname : "stdout");
  540.             gsm_destroy(r);
  541.             return -1;
  542.         }
  543.     }
  544.     if (cc < 0) {
  545.                 perror(inname ? inname : "<stdin>");
  546.                 fprintf(stderr, "%s: error reading from %s\n",
  547.                         progname, inname ? inname : "<stdin>");
  548.         gsm_destroy(r);
  549.         return -1;
  550.     }
  551.     gsm_destroy(r);
  552.  
  553.     return 0;
  554. }
  555.  
  556. int process_decode P0()
  557. {
  558.     gsm        r;
  559.     gsm_frame    s;
  560.     gsm_signal    d[ 160 ];
  561.  
  562.     int        cc, cw;
  563.  
  564.     if (!(r = gsm_create())) return -1;
  565.     (void)gsm_option(r, GSM_OPT_FAST,    &f_fast);
  566.     (void)gsm_option(r, GSM_OPT_VERBOSE, &f_verbose);
  567.  
  568.     while ((cc = fread(s, 1, sizeof(s), in)) > 0) {
  569.  
  570.         if (cc != sizeof(s)) {
  571.             if (cc >= 0) fprintf(stderr,
  572.                         "%s: incomplete frame (%d byte%s missing) from %s\n",
  573.                     progname, sizeof(s) - cc,
  574.                                         "s" + (sizeof(s) - cc == 1),
  575.                                         inname ? inname : "<stdin>" );
  576.             gsm_destroy(r);
  577.             return -1;
  578.         }
  579.  
  580.         if (gsm_decode(r, s, d)) {
  581.                         fprintf(stderr, "%s: bad frame in %s\n", 
  582.                                 progname, outname ? outname : "stdout");
  583.             gsm_destroy(r);
  584.             return -1;
  585.         }
  586.  
  587.         if ((*output)(d) < 0) {
  588.             perror(outname);
  589.                         fprintf(stderr, "%s: error writing to %s\n",
  590.                     progname, outname);
  591.             gsm_destroy(r);
  592.             return -1;
  593.         }
  594.     }
  595.  
  596.     if (cc < 0) {
  597.                 perror(inname ? inname : "<stdin>" );
  598.                 fprintf(stderr, "%s: error reading from %s\n", progname,
  599.                         inname ? inname : "<stdin>");
  600.         gsm_destroy(r);
  601.         return -1;
  602.     }
  603.  
  604.     gsm_destroy(r);
  605.     return 0;
  606. }
  607.  
  608. int process P1((name), char * name)
  609. {
  610.     int    outfd    = -1;
  611.     char    * tmp;
  612.  
  613.     out    = (FILE *)0;
  614.     in    = (FILE *)0;
  615.  
  616.     outname = (char *)0;
  617.     inname    = (char *)0;
  618.  
  619.     if (  !open_input(  name, &instat )
  620.        || !open_output( name )
  621.        || (*(f_decode ? init_output    : init_input))()
  622.        || (*(f_decode ? process_decode : process_encode))()
  623.        || fflush(out) < 0
  624.        || ferror(out)) {
  625.  
  626. err:        if (out) {
  627.                         perror(outname ? outname : "stdout");
  628.                         fprintf(stderr, "%s: error writing \"%s\"\n",
  629.                                 progname, outname ? outname : "stdout");
  630.  
  631.             if (out != stdout) {
  632.                 (void)fclose(out);
  633.                 if (  unlink(outname) < 0
  634.                    && errno != ENOENT
  635.                    && errno != EINTR) {
  636.  
  637.                     perror(outname);
  638.                     fprintf(stderr,
  639.                                                 "%s: could not unlink \"%s\"\n",
  640.                         progname, outname);
  641.                 }
  642.             }
  643.         }
  644.  
  645.         if (in && in != stdin) fclose(in);
  646.  
  647.         if (inname  && inname  != name) free(inname);
  648.         if (outname && outname != name) free(outname);
  649.  
  650.         return -1;
  651.     }
  652.  
  653.     if (out != stdout) {
  654.  
  655.         update_times();
  656.         update_mode ();
  657.         update_own  ();
  658.  
  659.         if (fclose(out) < 0) goto err;
  660.         free(outname);
  661.         outname = (char *)0;
  662.     }
  663.  
  664.     if (in    != stdin) {
  665.         fclose(in);
  666.         if (!f_cat && !f_precious) {
  667.             if (unlink(inname) < 0) {
  668.                 perror(inname);
  669.                 fprintf(stderr,
  670.                                         "%s: source \"%s\" not deleted.\n",
  671.                     progname, inname);
  672.             }
  673.         }
  674.         free(inname);
  675.         inname = (char *)0;
  676.     }
  677.     return 0;
  678. }
  679.  
  680. static void version P0()
  681. {
  682.         printf( "%s 1.0, version %s\n",
  683.         progname,
  684.                 "$Id: toast.c,v 1.3 1993/01/29 18:19:25 jutta Exp $" );
  685. }
  686.  
  687. static void help P0()
  688. {
  689.         printf("Usage: %s [-fcpdhvaulsF] [files...]\n", progname);
  690.         printf("\n");
  691.  
  692.         printf(" -f  force     Replace existing files without asking\n");
  693.         printf(" -c  cat       Write to stdout, do not remove source files\n");
  694.         printf(" -d  decode    Decode data (default is encode)\n");
  695.         printf(" -p  precious  Do not delete the source\n");
  696.         printf("\n");
  697.  
  698.         printf(" -u  u-law     Force 8 kHz/8 bit u-law in/output format\n");
  699.         printf(" -s  sun .au   Force Sun .au u-law in/output format\n");
  700.         printf(" -a  A-law     Force 8 kHz/8 bit A-law in/output format\n");
  701.         printf(" -l  linear    Force 16 bit linear in/output format\n");
  702.         printf("\n");
  703.  
  704.         printf(" -F  fast      Sacrifice conformance to performance\n");
  705.         printf(" -v  version   Show version information\n");
  706.         printf(" -h  help      Print this text\n");
  707.         printf("\n");
  708. }
  709.  
  710.  
  711. void set_format P1((f), struct fmtdesc * f)
  712. {
  713.     if (f_format && f_format != f) {
  714.         fprintf( stderr,
  715.         "%s: only one of -[uals] is possible (%s -h for help)\n",
  716.             progname, progname);
  717.         exit(1);
  718.     }
  719.  
  720.     f_format = f;
  721. }
  722.  
  723. int main P2((ac, av), int ac, char **av)
  724. {
  725.     int        opt;
  726.     extern int    optind;
  727.     extern char    * optarg;
  728.  
  729.     parse_argv0( *av );
  730.  
  731.         while ((opt = getopt(ac, av, "fcdpvhuaslVF")) != EOF)
  732.     switch (opt) {
  733.  
  734.         case 'd': f_decode   = 1; break;
  735.         case 'f': f_force    = 1; break;
  736.         case 'c': f_cat      = 1; break;
  737.         case 'p': f_precious = 1; break;
  738.         case 'F': f_fast     = 1; break;
  739.  
  740. #ifndef NDEBUG
  741.         case 'V': f_verbose  = 1; break;        /* undocumented */
  742. #endif
  743.  
  744.         case 'u': set_format( &f_ulaw   ); break;
  745.         case 'l': set_format( &f_linear ); break;
  746.         case 'a': set_format( &f_alaw   ); break;
  747.         case 's': set_format( &f_audio  ); break;
  748.  
  749.         case 'v': version(); exit(0);
  750.         case 'h': help();    exit(0);
  751.  
  752.     default: 
  753.         fprintf(stderr,
  754.                         "Usage: %s [-fcpdhvuaslF] [files...] (-h for help)\n",
  755.             progname);
  756.         exit(1);
  757.     }
  758.  
  759.     f_precious |= f_cat;
  760.  
  761.     av += optind;
  762.     ac -= optind;
  763.  
  764.     catch_signals(onintr);
  765.  
  766.     if (ac <= 0) process( (char *)0 );
  767.     else while (ac--) process( *av++ );
  768.  
  769.     exit(0);
  770. }
  771.